import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class CustomConnectionPoolMain {
	private static final String DB_URL = "jdbc:mysql://localhost:3306/pool_db?user=root&password=123456";

	private static final int SHUTDOWN_TIMEOUT_SEC = 5;
	private static final int SIZE = 16;
	private static final int TASK_COUNT = 1024;

	private static ExecutorService service;
	private static AtomicInteger counter = new AtomicInteger();

	public static void main(String... args) throws InterruptedException {
		service = Executors.newFixedThreadPool(SIZE);
		final CustomConnectionPool pool = new CustomConnectionPool(DB_URL, SIZE);

		System.out.println("Running statements...");

		final CountDownLatch countdown = new CountDownLatch(TASK_COUNT);

		for (int i = 0; i < TASK_COUNT; i++) {
			service.submit(new Runnable() {
				@Override
				public void run() {
					try {
						int rand = (int) (Math.random() * Integer.MAX_VALUE);
						Connection connection = pool.getConnection();
						PreparedStatement ps = connection
								.prepareStatement("INSERT INTO t_table (value) VALUES(?)");
						ps.setInt(1, rand);
						ps.execute();
						ps.close();
						pool.releaseConnection(connection);
						System.out.println("Executed statement #"
								+ counter.incrementAndGet() + ".");
					} catch (InterruptedException e) {
						System.err
								.println("Oops. Waiting for a connection was interrupted.");
					} catch (SQLException e) {
						System.err.println("Exception while executing query.");
					}
					countdown.countDown();
				}
			});
		}

		countdown.await();
		service.shutdown();
		service.awaitTermination(SHUTDOWN_TIMEOUT_SEC, TimeUnit.SECONDS);

		System.out.println("Done.");
	}
}
